#_*_:encoding:utf-8_*_
__author__ = 'toriycn'
import json
from app.monitors.server.conf import hosts,settings
import time
import operator
import threading,traceback

class MontorDataDual(threading.Thread):

    def __init__(self,main_ins):
        threading.Thread.__init__(self)
        self.main_ins = main_ins
        
    def run(self):
        self.data_process()

    #设定所有的主机配置信息到redis里，其它的主机可以从这里获取监控信息。
    def push_all_configs_into_redis(self,host_groups):
       host_config_dic = {}
       for group in host_groups:
           for hosts in group.hosts:
               if hosts not in host_config_dic.keys():
                   host_config_dic[hosts] = {}
               for s in group.services:
                   _serviceTemp = self.main_ins.hostTemplate.getService(s)
                   #插件名，间隔时间
                   host_config_dic[hosts][_serviceTemp.name]= [_serviceTemp.plugin_name,_serviceTemp.interval]
       for h,v in host_config_dic.items():
           host_config_key="HostConfig::%s"%h
           self.main_ins.r.set(host_config_key,json.dumps(v))
    #处理采集到的数据

    #分时数据处理
    def data_process(self):
        print("going to handle monitor data--")
        while True:
            all_host_config = self.main_ins.fetch_all_configs()
            for ip,service_dic in all_host_config.items():
                for service_name,s_instance in service_dic.items():
                    service_redis_key = settings.REDIS_KEY_TEMPLATE %(ip,service_name)
                    #从redis中获取采集到的最新的数据
                    s_data = self.main_ins.r.get(service_redis_key)
                    if s_data:
                         try:
                             s_data = str(s_data,"utf-8")
                             s_data  =  json.loads(s_data)
                             time_stamp = s_data['time_stamp']
                             #如果时间大于间隔时间，进行业务处理
                             if time.time() - time_stamp < s_instance.interval:
                                 if s_data ['data']['status'] == 0 :
                                     for item_key,val in s_instance.triggers.items():
                                         self.service_item_handle(item_key,val,s_data,ip,service_name)
                                 else:
                                     print("Host[%s] service[%s] plugin error"%(ip,service_name))
                             else:
                                 expired_time = time.time() - time_stamp - s_instance.interval
                                 print("Host[%s] service[%s] data expireds[%s] secs" %(ip,service_name,expired_time))
                         except:
                            traceback.print_exc()
                            print("service [%s] host [%s] data has error"%(service_name,ip))
                    else:
                         print("no data found in redis for service [%s] host [%s]"%(service_name,ip))
            time.sleep(1)


    def record_redis_data(self,item_key,client_service_data,item_data):
            service_date_redisKey = settings.REDIS_KEY_TEMPLATE_HIS_DATA %\
                                    (client_service_data['host'],
                                     client_service_data['service'],
                                     item_key)
            redis_His_Data = self.main_ins.r.get(service_date_redisKey)

            if redis_His_Data is None :
                redis_His_Data = {
                    "real":[],
                    "ten":[],
                    "hours":[],
                    "days":[],
                    "month":[]
                }
            else:
                redis_His_Data = eval(redis_His_Data)

            item_time = client_service_data['time_stamp']

            for item in redis_His_Data["real"]:
                if item[0] == item_time:
                    #已经被添加过的不再处理。
                    return False,redis_His_Data

            redis_His_Data["real"].append([item_time,float(item_data)])
            length = len(redis_His_Data["real"])

            if length > settings.MAX_REAL_DATA_STORE_TIMES:
                #弹出最后的一个
                del redis_His_Data["real"][0]

            lastRedisData = redis_His_Data["ten"]
            if len(lastRedisData) <=0:
                redis_His_Data["ten"].append([client_service_data['time_stamp'],item_data])
            else:
                if len(lastRedisData)> settings.MAX_REAL_DATA_STORE_TIMES:
                   del redis_His_Data["ten"][0]
                #如果最后一个时间与当前时间间隔10分钟，那么新增，如果十分钟以内，那么更新
                lastDate=  lastRedisData[-1][0]
                lastValue = lastRedisData[-1][1]
                if (time.time() - lastDate  ) > 600:
                    redis_His_Data["ten"].append([client_service_data['time_stamp'],item_data])
                else:
                    redis_His_Data["ten"].pop()
                    lastValue = (float(lastValue) + float(item_data))/2
                    redis_His_Data["ten"].append([client_service_data['time_stamp'],lastValue])

            self.main_ins.r.set(service_date_redisKey,redis_His_Data)
            return True,redis_His_Data

    #服务处理
    def service_item_handle(self,item_key,val_dic,client_service_data,hostip,service):
        #数据记录到redis中，redis中的数据是不会重复的
        item_data = client_service_data['data'][item_key]
        addResult,redis_His_Data = self.record_redis_data(item_key,client_service_data,item_data)
        if addResult == False:
            return
        #提醒值
        warning_val = val_dic['warning']
        #阀值
        critical_val = val_dic['critical']
        #比较函数
        oper_func = getattr(operator,val_dic['operator'])
        warning_res = False
        critical_res = False
        #非数值型的不作为比较
        if val_dic['data_type'] is not float:
            warning_res = oper_func(item_data,warning_val)
            critical_res = oper_func(item_data,critical_val)
        else:
            warning_res = oper_func(float(item_data),warning_val)
            critical_res = oper_func(float(item_data),critical_val)
            #比较完成后，记录日志

        # print(">>>>>>>>11111111111111",warning_res,critical_res,redis_His_Data)
        #当有报警或者有严重的级别
        if warning_res or critical_res:
            if val_dic['func'] == 'avg':
                iitem_montitor_count = int(val_dic['count'])
                redis_His_Data_temp =  redis_His_Data["real"]
                avgvalue = 0
                for his_item in  redis_His_Data_temp:
                    avgvalue = avgvalue+his_item[1]
                if avgvalue < iitem_montitor_count:
                    return
            elif val_dic['func'] == 'hint':
                iitem_montitor_count = int(val_dic['count'])
                redis_His_Data_temp =  redis_His_Data["real"]
                avgvalue = 0
                for his_item in  redis_His_Data_temp:
                    if his_item[1] == 1:
                        avgvalue = avgvalue+1
                if avgvalue < iitem_montitor_count :
                    return
            else:
                return
            #报警
            alertMessage = {}
            #主机，服务，trigger
            alertMessage['host'] = hostip
            alertMessage['service'] = service
            alertMessage['item_key'] = item_key
            alertMessage['item_data'] = item_data
            if warning_res == True:
              alertMessage['item_alert_type'] = "waring"
            if critical_res == True:
              alertMessage['item_alert_type'] = "critical"
            #产生一个监控信息，并发送
            self.main_ins.alertR.public(json.dumps(alertMessage))


class AlertDataDual(threading.Thread):

    def __init__(self,main_ins):
        threading.Thread.__init__(self)
        self.main_ins = main_ins

    def run(self):
        self.data_process()

    def fetch_service_data(self):
        service_data= {}

    def data_process(self):
        pub = self.main_ins.alertR.subscribe()
        while True:
            all_host_config = self.main_ins.fetch_all_configs()
            #处理数据
            host_service_data = pub.parse_response()
            host_service_data = json.loads(str(host_service_data[2],encoding="utf-8"))
            host_service_data['time_stamp'] = time.time()
            '''
            设定时间戳，根据报警类型从报警的内容从配置文件中获取该报警的次数
            和redis中的这个报警数据进行匹配，如果超过报警的次数，进行报警。
            '''
            redis_key_alertData = "ALERT_DATA_KEY::%s::%s" %(host_service_data['service'],host_service_data['host'])
            # print(redis_key_alertData)


